/*
 * JNIUpstream.cpp
 *
 *  Created on: 2012/01/02
 *      Author: nobnak
 */
#include <assert.h>
#include <linux/stddef.h>
#include "JNIUpstream.h"

JNIUpstream::JNIUpstream(JavaVM *vm) {
	this->vm = vm;
}

JNIUpstream::~JNIUpstream() {
}

void JNIUpstream::write(unsigned char *src, int n) {
	// Get JNIEnv
	jint status;
	JNIEnv *env = getEnv();
	if (env == NULL)
		return;

	jclass clazz = env->GetObjectClass(callbackListener);
	if (clazz == NULL) {
		vm->DetachCurrentThread();
		return;
	}
	jmethodID jm = env->GetMethodID(clazz, "read", "([B)V");
	assert(jm != NULL);
	if (jm == NULL) {
		vm->DetachCurrentThread();
		return;
	}

	jbyteArray jpcm = env->NewByteArray(n);
	assert(jpcm != NULL);
	if (jpcm == NULL) {
		vm->DetachCurrentThread();
		return;
	}
	env->SetByteArrayRegion(jpcm, 0, n, (jbyte*) src);
	env->CallVoidMethod(callbackListener, jm, jpcm);
	env->DeleteLocalRef(jpcm);
	vm->DetachCurrentThread();
}

void JNIUpstream::setListener(JNIEnv *env, jobject callbackListener) {
	assert(callbackListener != NULL);
	if (callbackListener == NULL) {
		throw "Listener is null";
	}

	deleteListener(env);

	this->callbackListener = env->NewGlobalRef(callbackListener);
	assert(this->callbackListener != NULL);
	if (this->callbackListener == NULL) {
		throw "Failed to make global ref of the listener";
	}
}

void JNIUpstream::deleteListener(JNIEnv *env) {
	if (callbackListener != NULL) {
		env->DeleteGlobalRef(callbackListener);
		callbackListener = NULL;
	}
}

void JNIUpstream::end() {
	// Get JNIEnv
	jint status;
	JNIEnv *env = getEnv();
	if (env == NULL)
		return;

	jclass clazz = env->GetObjectClass(callbackListener);
	if (clazz == NULL) {
		vm->DetachCurrentThread();
		return;
	}
	jmethodID jm = env->GetMethodID(clazz, "end", "()V");
	assert(jm != NULL);
	if (jm == NULL) {
		vm->DetachCurrentThread();
		return;
	}

	env->CallVoidMethod(callbackListener, jm);

	vm->DetachCurrentThread();
}
JNIEnv *JNIUpstream::getEnv() {
	// Get JNIEnv
	jint status;
	JNIEnv *env;
	status = vm->GetEnv((void **) &env, JNI_VERSION_1_6);
	if (status != JNI_OK)
		status = vm->AttachCurrentThread(&env, NULL);
	assert(status == JNI_OK);
	if (status != JNI_OK)
		return NULL;
	return env;
}
